El primero está basado en un histórico de ventas de videojuegos de varias compañías en distintas plataformas desde el inicio del mercado de este producto. Se pretende obtener tendencias, deducir quién controla el mercado, puntos de crisis o cambio de consumo, y cuáles son las plataformas que dominan el mercado actual.

Ideas a estudiar en el dataset -Comparar las ventas entre regiones. Observar relaciones y modelos de influencia entre las mismas. -Ver qué géneros son más populares en regiones y han cambiado a lo largo del tiempo significativamente. -El alzamiento y caída de diferentes plataformas a lo largo de los años.

library(reshape2) #facilita la trasnformación entre diferentes formatos de datos.
library(plotly) #https://plot.ly/r/
Loading required package: ggplot2
Use suppressPackageStartupMessages() to eliminate package startup messages.

Attaching package: ‘plotly’

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout
video_games<-read.csv("recursos/vgsales.csv")
typeof(video_games)
[1] "list"
head(video_games)
video_games$Year <- ordered(video_games$Year)
video_games <- video_games[video_games$Year<2017,]
video_games

Vamos a ver la proporción de ventas en relación al total

num_Sales <- video_games[,c("NA_Sales","EU_Sales","JP_Sales","Other_Sales","Global_Sales")]
apply(num_Sales,2,sum)/apply(num_Sales['Global_Sales'],2,sum)*100
    NA_Sales     EU_Sales     JP_Sales  Other_Sales Global_Sales 
   49.128687    27.314224    14.560625     8.945445   100.000000 

De forma general puede apreciarse que hay una subida prograsiva desde 1996 hasta 2008. A partir de este momento comienza la caidahasta 2016.

ggplot(data=video_games, aes(x=Year, y=Global_Sales, fill=Genre)) +
    geom_bar(stat="identity")

ggplotly()

-Comparar las ventas entre regiones. Observar relaciones y modelos de influencia entre las mismas.

head(video_games)
#video_games_NA=video_games[c("Year","NA_Sales")]
#video_games_EU=video_games[c("Year","EU_Sales")]
#video_games_JP=video_games[c("Year","JP_Sales")]
ggplot(data=video_games, aes(x=Year, y=NA_Sales, fill=Genre)) +
    geom_bar(stat="identity")

ggplot(data=video_games, aes(x=Year, y=EU_Sales, fill=Genre)) +
    geom_bar(stat="identity")

ggplot(data=video_games, aes(x=Year, y=JP_Sales, fill=Genre)) +
    geom_bar(stat="identity")

ggplot(data=video_games, aes(x=Year, y=Other_Sales, fill=Genre)) +
    geom_bar(stat="identity")

Se aprecia que hay una influencia clara entre Europa y EEUU. Japón va un poco mas por libre, aunque se puede observar que los grandes cambios de tendencia también le afectan. Se podría decir también que Japón es quien inicia esas tendencias. Cuando empiezan a subir las ventas, a los pocos años suben también en EEUU y Europa. Lo mismo cuando comienzan a caer las ventas. El resto del mundo sigue también la tendencia de Europa y EEUU.

#Preparo los datos para poder mostrar una tendencia de ventas por región
library(dplyr)  #funciones para manipular data frames.

Attaching package: ‘dplyr’

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
na <- video_games %>% select(Year,NA_Sales) %>% group_by(Year) %>% summarise(s=sum(NA_Sales))
eu <- video_games %>% select(Year,EU_Sales) %>% group_by(Year) %>% summarise(s=sum(EU_Sales))
jp <- video_games %>% select(Year,JP_Sales) %>%group_by(Year) %>% summarise(s=sum(JP_Sales))
oth <- video_games %>% select(Year,Other_Sales) %>% group_by(Year) %>% summarise(s=sum(Other_Sales))
data_sales <- data.frame(year = c(1980:2016),oth$s,jp$s,eu$s,na$s)
data_sales
ggplot(data_sales, aes((year))) + 
  geom_line(aes(y = na$s , colour = "NA_Sales"),size=1) + 
  geom_line(aes(y = eu$s, colour = "EU_Sales"),size=1)+
  geom_line(aes(y= jp$s ,colour='JP_Sales'),size=1)+
  geom_line(aes(y=oth$s,colour='Other_Sales'),size=1) + ylab('Ventas en Millones') +
  scale_x_continuous(breaks = scales::pretty_breaks(n = 9)) +  #Numero de divisiones en X.
  ggtitle("Evolución de ventas a lo largo del tiempo") +
  #theme(axis.text.x = element_text(angle = 90, size = 10, vjust = 0.4),legend.position = "top")
  theme(plot.background = element_rect(fill = "grey"),legend.text = element_text(size = 8, colour = "blue"),legend.title = element_text(face="bold"),legend.position = "top")

#hay diferentes tipos de themes predefinidos: theme_bf... theme_gray...  Ver https://ggplot2.tidyverse.org/reference/theme.html

Se observa una dominación en las ventas por parte de NA entre 2000 y 2010, A partir de 2008 y coincidiendo con la crisis global económica, hay una caída fuerte en todas las regiones y la dominación cesa.

Hay por lo tanto puntos críticos en la evolución de las ventas en 1995, 2000 y 2008 (se podría indagar qué motivos forzaron los cambios en las fechas previas no comentadas).

A su vez se observa que la serie NA y EU están fuertemente ligadas.


-El alzamiento y caída de diferentes plataformas a lo largo de los años.

platforms <- video_games[,c("Platform","Year","Global_Sales")]
platforms <- platforms %>% group_by(Platform,Year) %>% summarise_all(funs(sum))
platforms_1980<-subset(platforms,Year<1990,select = Platform:Global_Sales)
platforms_1990<-subset(platforms,Year>=1990 & Year<2000,select = Platform:Global_Sales)
platforms_2000<-subset(platforms,Year>=2000 & Year<2010,select = Platform:Global_Sales)
platforms_2010<-subset(platforms,Year>=2010,select = Platform:Global_Sales)
sp <- ggplot(platforms_1980, aes(x=Year, y=Global_Sales)) +
  geom_point(shape=1) +
  geom_line(group = 1)
sp + facet_grid(Platform ~ .)

sp <- ggplot(platforms_1990, aes(x=Year, y=Global_Sales)) +
  geom_point(shape=1) +
  geom_line(group = 1)
sp + facet_wrap(Platform ~ ., ncol=3) 

sp <- ggplot(platforms_2000, aes(x=Year, y=Global_Sales)) +
  geom_point(shape=1) +
  geom_line(group = 1)
sp + facet_wrap(Platform ~ ., ncol=3)  

sp <- ggplot(platforms_2010, aes(x=Year, y=Global_Sales)) +
  geom_point(shape=1) +
  geom_line(group = 1)
sp + facet_wrap(Platform ~ ., ncol=3)  

#Para los gráficos de líneas, los puntos de datos deben agruparse para que sepa qué puntos conectar. En este caso, es simple: todos los puntos deben estar conectados, por lo que group = 1. Cuando se utilizan más variables y se dibujan varias líneas, la agrupación de líneas se realiza generalmente por variable.

Ver qué géneros son más populares en regiones y han cambiado a lo largo del tiempo significativamente.

Vamos a ver el TOP de los géneros por año

#La función top_n te permite quedarte con el primer valor:
top_genre_year <- video_games[,c("Genre","Year","Global_Sales")]
top_genre_year <- top_genre_year %>% group_by(Year,Genre) %>% summarise(ventas=sum(Global_Sales)) %>% top_n(1)
Selecting by ventas
top_genre_japan <- video_games[,c("Genre","Year","JP_Sales")]
top_genre_japan <- top_genre_japan %>% group_by(Year,Genre) %>% summarise(ventas=sum(JP_Sales)) %>% top_n(1)
Selecting by ventas
ggplot(data=top_genre_year, aes(x=Year, y=ventas, fill=Genre)) +
    geom_bar(stat="identity") +
    ggtitle("Top Genero por año") +
    theme(axis.text.x = element_text(angle = 90, size = 10, vjust = 0.4),legend.position = "top")

ggplot(data=top_genre_japan, aes(x=Year, y=ventas, fill=Genre)) +
    geom_bar(stat="identity") +
    ggtitle("Top Genero por año Japon") +
    theme(axis.text.x = element_text(angle = 90, size = 10, vjust = 0.4),legend.position = "top")

Observamos que la preferencia en género de videojuego en Japón es por los juegos de rol mientras que globalmente es por los de acción. Esto es una característica cualitativa diferenciadora de este mercado respecto al global.


Realizamos un contraste Chi Cuadrado de bondad de ajuste de dinero en ventas en cada género con las combinaciones: - EU vs NA - EU vs JP - JP vs NA

Agrupamos desde 2008 que es el último cambio de la serie y hacemos contrastes:

EU_gen <- video_games[video_games$Year>=2008,] %>% group_by(Genre) %>% 
         summarize(Revenue = sum(EU_Sales))
NA_gen <- video_games[video_games$Year>=2008,] %>% group_by(Genre) %>% 
         summarize(Revenue = sum(NA_Sales))
JP_gen <- video_games[video_games$Year>=2008,] %>% group_by(Genre) %>% 
         summarize(Revenue = sum(JP_Sales))
Global_gen <- video_games[video_games$Year>=2008,] %>% group_by(Genre) %>% 
         summarize(Revenue = sum(Global_Sales))
Other_gen <- video_games[video_games$Year>=2008,] %>% group_by(Genre) %>% 
         summarize(Revenue = sum(Other_Sales))
NA_gen
ggplot(EU_gen,aes(x=Genre,y=Revenue))+
  geom_bar(stat='identity')+ 
  ggtitle("Genre of Games Purchased in EU")+
  ylab("In Millions")+
  theme(axis.text.x = element_text(angle = 90, size = 10, vjust = 0.4))

ggplot(JP_gen,aes(x=Genre,y=Revenue))+
  geom_bar(stat='identity')+ 
  ggtitle("Genre of Games Purchased in JP")+
  ylab("In Millions")+
  theme(axis.text.x = element_text(angle = 90, size = 10, vjust = 0.4))

ggplot(NA_gen,aes(x=Genre,y=Revenue))+
  geom_bar(stat='identity')+ 
  ggtitle("Genre of Games Purchased in NA")+
  ylab("In Millions")+
  theme(axis.text.x = element_text(angle = 90, size = 10, vjust = 0.4))

ggplot(NA_gen,aes(x=Genre,y=Revenue))+
  geom_bar(stat='identity')+ 
  ggtitle("Genre of Games Purchased in Other")+
  ylab("In Millions")+
  theme(axis.text.x = element_text(angle = 90, size = 10, vjust = 0.4))

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKRWwgcHJpbWVybyBlc3TDoSBiYXNhZG8gZW4gdW4gaGlzdMOzcmljbyBkZSB2ZW50YXMgZGUgdmlkZW9qdWVnb3MgZGUgdmFyaWFzIGNvbXBhw7HDrWFzIGVuIGRpc3RpbnRhcyBwbGF0YWZvcm1hcyBkZXNkZSBlbCBpbmljaW8gZGVsIG1lcmNhZG8gZGUgZXN0ZSBwcm9kdWN0by4gU2UgcHJldGVuZGUgb2J0ZW5lciB0ZW5kZW5jaWFzLCBkZWR1Y2lyIHF1acOpbiBjb250cm9sYSBlbCBtZXJjYWRvLCBwdW50b3MgZGUgY3Jpc2lzIG8gY2FtYmlvIGRlIGNvbnN1bW8sIHkgY3XDoWxlcyBzb24gbGFzIHBsYXRhZm9ybWFzIHF1ZSBkb21pbmFuIGVsIG1lcmNhZG8gYWN0dWFsLgoKCklkZWFzIGEgZXN0dWRpYXIgZW4gZWwgZGF0YXNldAotQ29tcGFyYXIgbGFzIHZlbnRhcyBlbnRyZSByZWdpb25lcy4gT2JzZXJ2YXIgcmVsYWNpb25lcyB5IG1vZGVsb3MgZGUgaW5mbHVlbmNpYSBlbnRyZSBsYXMgbWlzbWFzLgotVmVyIHF1w6kgZ8OpbmVyb3Mgc29uIG3DoXMgcG9wdWxhcmVzIGVuIHJlZ2lvbmVzIHkgaGFuIGNhbWJpYWRvIGEgbG8gbGFyZ28gZGVsIHRpZW1wbyBzaWduaWZpY2F0aXZhbWVudGUuCi1FbCBhbHphbWllbnRvIHkgY2HDrWRhIGRlIGRpZmVyZW50ZXMgcGxhdGFmb3JtYXMgYSBsbyBsYXJnbyBkZSBsb3MgYcOxb3MuCgpgYGB7cn0KbGlicmFyeShyZXNoYXBlMikgI2ZhY2lsaXRhIGxhIHRyYXNuZm9ybWFjacOzbiBlbnRyZSBkaWZlcmVudGVzIGZvcm1hdG9zIGRlIGRhdG9zLgpsaWJyYXJ5KHBsb3RseSkgI2h0dHBzOi8vcGxvdC5seS9yLwpgYGAKCgoKYGBge3J9CnZpZGVvX2dhbWVzPC1yZWFkLmNzdigicmVjdXJzb3MvdmdzYWxlcy5jc3YiKQp0eXBlb2YodmlkZW9fZ2FtZXMpCmhlYWQodmlkZW9fZ2FtZXMpCgp2aWRlb19nYW1lcyRZZWFyIDwtIG9yZGVyZWQodmlkZW9fZ2FtZXMkWWVhcikKdmlkZW9fZ2FtZXMgPC0gdmlkZW9fZ2FtZXNbdmlkZW9fZ2FtZXMkWWVhcjwyMDE3LF0KdmlkZW9fZ2FtZXMKCmBgYAoKClZhbW9zIGEgdmVyIGxhIHByb3BvcmNpw7NuIGRlIHZlbnRhcyBlbiByZWxhY2nDs24gYWwgdG90YWwKYGBge3J9Cm51bV9TYWxlcyA8LSB2aWRlb19nYW1lc1ssYygiTkFfU2FsZXMiLCJFVV9TYWxlcyIsIkpQX1NhbGVzIiwiT3RoZXJfU2FsZXMiLCJHbG9iYWxfU2FsZXMiKV0KYXBwbHkobnVtX1NhbGVzLDIsc3VtKS9hcHBseShudW1fU2FsZXNbJ0dsb2JhbF9TYWxlcyddLDIsc3VtKSoxMDAKCmBgYAoKRGUgZm9ybWEgZ2VuZXJhbCBwdWVkZSBhcHJlY2lhcnNlIHF1ZSBoYXkgdW5hIHN1YmlkYSBwcm9ncmFzaXZhIGRlc2RlIDE5OTYgaGFzdGEgMjAwOC4gQSBwYXJ0aXIgZGUgZXN0ZSBtb21lbnRvIGNvbWllbnphIGxhIGNhaWRhaGFzdGEgMjAxNi4gCgpgYGB7cn0KZ2dwbG90KGRhdGE9dmlkZW9fZ2FtZXMsIGFlcyh4PVllYXIsIHk9R2xvYmFsX1NhbGVzLCBmaWxsPUdlbnJlKSkgKwogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKQoKZ2dwbG90bHkoKQpgYGAKCi1Db21wYXJhciBsYXMgdmVudGFzIGVudHJlIHJlZ2lvbmVzLiBPYnNlcnZhciByZWxhY2lvbmVzIHkgbW9kZWxvcyBkZSBpbmZsdWVuY2lhIGVudHJlIGxhcyBtaXNtYXMuCgpgYGB7cn0KaGVhZCh2aWRlb19nYW1lcykKCiN2aWRlb19nYW1lc19OQT12aWRlb19nYW1lc1tjKCJZZWFyIiwiTkFfU2FsZXMiKV0KI3ZpZGVvX2dhbWVzX0VVPXZpZGVvX2dhbWVzW2MoIlllYXIiLCJFVV9TYWxlcyIpXQojdmlkZW9fZ2FtZXNfSlA9dmlkZW9fZ2FtZXNbYygiWWVhciIsIkpQX1NhbGVzIildCgpnZ3Bsb3QoZGF0YT12aWRlb19nYW1lcywgYWVzKHg9WWVhciwgeT1OQV9TYWxlcywgZmlsbD1HZW5yZSkpICsKICAgIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikKCmdncGxvdChkYXRhPXZpZGVvX2dhbWVzLCBhZXMoeD1ZZWFyLCB5PUVVX1NhbGVzLCBmaWxsPUdlbnJlKSkgKwogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKQoKZ2dwbG90KGRhdGE9dmlkZW9fZ2FtZXMsIGFlcyh4PVllYXIsIHk9SlBfU2FsZXMsIGZpbGw9R2VucmUpKSArCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpCgpnZ3Bsb3QoZGF0YT12aWRlb19nYW1lcywgYWVzKHg9WWVhciwgeT1PdGhlcl9TYWxlcywgZmlsbD1HZW5yZSkpICsKICAgIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikKYGBgClNlIGFwcmVjaWEgcXVlIGhheSB1bmEgaW5mbHVlbmNpYSBjbGFyYSBlbnRyZSBFdXJvcGEgeSBFRVVVLiBKYXDDs24gdmEgdW4gcG9jbyBtYXMgcG9yIGxpYnJlLCBhdW5xdWUgc2UgcHVlZGUgb2JzZXJ2YXIgcXVlIGxvcyBncmFuZGVzIGNhbWJpb3MgZGUgdGVuZGVuY2lhIHRhbWJpw6luIGxlIGFmZWN0YW4uIFNlIHBvZHLDrWEgZGVjaXIgdGFtYmnDqW4gcXVlIEphcMOzbiBlcyBxdWllbiBpbmljaWEgZXNhcyB0ZW5kZW5jaWFzLiBDdWFuZG8gZW1waWV6YW4gYSBzdWJpciBsYXMgdmVudGFzLCBhIGxvcyBwb2NvcyBhw7FvcyBzdWJlbiB0YW1iacOpbiBlbiBFRVVVIHkgRXVyb3BhLiBMbyBtaXNtbyBjdWFuZG8gY29taWVuemFuIGEgY2FlciBsYXMgdmVudGFzLiBFbCByZXN0byBkZWwgbXVuZG8gc2lndWUgdGFtYmnDqW4gbGEgdGVuZGVuY2lhIGRlIEV1cm9wYSB5IEVFVVUuCgpgYGB7cn0KI1ByZXBhcm8gbG9zIGRhdG9zIHBhcmEgcG9kZXIgbW9zdHJhciB1bmEgdGVuZGVuY2lhIGRlIHZlbnRhcyBwb3IgcmVnacOzbgoKbGlicmFyeShkcGx5cikgICNmdW5jaW9uZXMgcGFyYSBtYW5pcHVsYXIgZGF0YSBmcmFtZXMuCgpuYSA8LSB2aWRlb19nYW1lcyAlPiUgc2VsZWN0KFllYXIsTkFfU2FsZXMpICU+JSBncm91cF9ieShZZWFyKSAlPiUgc3VtbWFyaXNlKHM9c3VtKE5BX1NhbGVzKSkKCmV1IDwtIHZpZGVvX2dhbWVzICU+JSBzZWxlY3QoWWVhcixFVV9TYWxlcykgJT4lIGdyb3VwX2J5KFllYXIpICU+JSBzdW1tYXJpc2Uocz1zdW0oRVVfU2FsZXMpKQoKanAgPC0gdmlkZW9fZ2FtZXMgJT4lIHNlbGVjdChZZWFyLEpQX1NhbGVzKSAlPiVncm91cF9ieShZZWFyKSAlPiUgc3VtbWFyaXNlKHM9c3VtKEpQX1NhbGVzKSkKCm90aCA8LSB2aWRlb19nYW1lcyAlPiUgc2VsZWN0KFllYXIsT3RoZXJfU2FsZXMpICU+JSBncm91cF9ieShZZWFyKSAlPiUgc3VtbWFyaXNlKHM9c3VtKE90aGVyX1NhbGVzKSkKCmRhdGFfc2FsZXMgPC0gZGF0YS5mcmFtZSh5ZWFyID0gYygxOTgwOjIwMTYpLG90aCRzLGpwJHMsZXUkcyxuYSRzKQpkYXRhX3NhbGVzCgpnZ3Bsb3QoZGF0YV9zYWxlcywgYWVzKCh5ZWFyKSkpICsgCiAgZ2VvbV9saW5lKGFlcyh5ID0gbmEkcyAsIGNvbG91ciA9ICJOQV9TYWxlcyIpLHNpemU9MSkgKyAKICBnZW9tX2xpbmUoYWVzKHkgPSBldSRzLCBjb2xvdXIgPSAiRVVfU2FsZXMiKSxzaXplPTEpKwogIGdlb21fbGluZShhZXMoeT0ganAkcyAsY29sb3VyPSdKUF9TYWxlcycpLHNpemU9MSkrCiAgZ2VvbV9saW5lKGFlcyh5PW90aCRzLGNvbG91cj0nT3RoZXJfU2FsZXMnKSxzaXplPTEpICsgeWxhYignVmVudGFzIGVuIE1pbGxvbmVzJykgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzY2FsZXM6OnByZXR0eV9icmVha3MobiA9IDkpKSArICAjTnVtZXJvIGRlIGRpdmlzaW9uZXMgZW4gWC4KICBnZ3RpdGxlKCJFdm9sdWNpw7NuIGRlIHZlbnRhcyBhIGxvIGxhcmdvIGRlbCB0aWVtcG8iKSArCiAgI3RoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHNpemUgPSAxMCwgdmp1c3QgPSAwLjQpLGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQogIHRoZW1lKHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyZXkiKSxsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCwgY29sb3VyID0gImJsdWUiKSxsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZT0iYm9sZCIpLGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQoKI2hheSBkaWZlcmVudGVzIHRpcG9zIGRlIHRoZW1lcyBwcmVkZWZpbmlkb3M6IHRoZW1lX2JmLi4uIHRoZW1lX2dyYXkuLi4gIFZlciBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvdGhlbWUuaHRtbAoKYGBgClNlIG9ic2VydmEgdW5hIGRvbWluYWNpw7NuIGVuIGxhcyB2ZW50YXMgcG9yIHBhcnRlIGRlIE5BIGVudHJlIDIwMDAgeSAyMDEwLCBBIHBhcnRpciBkZSAyMDA4IHkgY29pbmNpZGllbmRvIGNvbiBsYSBjcmlzaXMgZ2xvYmFsIGVjb27Ds21pY2EsIGhheSB1bmEgY2HDrWRhIGZ1ZXJ0ZSBlbiB0b2RhcyBsYXMgcmVnaW9uZXMgeSBsYSBkb21pbmFjacOzbiBjZXNhLgoKSGF5IHBvciBsbyB0YW50byBwdW50b3MgY3LDrXRpY29zIGVuIGxhIGV2b2x1Y2nDs24gZGUgbGFzIHZlbnRhcyBlbiAxOTk1LCAyMDAwIHkgMjAwOCAoc2UgcG9kcsOtYSBpbmRhZ2FyIHF1w6kgbW90aXZvcyBmb3J6YXJvbiBsb3MgY2FtYmlvcyBlbiBsYXMgZmVjaGFzIHByZXZpYXMgbm8gY29tZW50YWRhcykuCgpBIHN1IHZleiBzZSBvYnNlcnZhIHF1ZSBsYSBzZXJpZSBOQSB5IEVVIGVzdMOhbiBmdWVydGVtZW50ZSBsaWdhZGFzLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCi1FbCBhbHphbWllbnRvIHkgY2HDrWRhIGRlIGRpZmVyZW50ZXMgcGxhdGFmb3JtYXMgYSBsbyBsYXJnbyBkZSBsb3MgYcOxb3MuCgpgYGB7cn0KcGxhdGZvcm1zIDwtIHZpZGVvX2dhbWVzWyxjKCJQbGF0Zm9ybSIsIlllYXIiLCJHbG9iYWxfU2FsZXMiKV0KcGxhdGZvcm1zIDwtIHBsYXRmb3JtcyAlPiUgZ3JvdXBfYnkoUGxhdGZvcm0sWWVhcikgJT4lIHN1bW1hcmlzZV9hbGwoZnVucyhzdW0pKQoKcGxhdGZvcm1zXzE5ODA8LXN1YnNldChwbGF0Zm9ybXMsWWVhcjwxOTkwLHNlbGVjdCA9IFBsYXRmb3JtOkdsb2JhbF9TYWxlcykKcGxhdGZvcm1zXzE5OTA8LXN1YnNldChwbGF0Zm9ybXMsWWVhcj49MTk5MCAmIFllYXI8MjAwMCxzZWxlY3QgPSBQbGF0Zm9ybTpHbG9iYWxfU2FsZXMpCnBsYXRmb3Jtc18yMDAwPC1zdWJzZXQocGxhdGZvcm1zLFllYXI+PTIwMDAgJiBZZWFyPDIwMTAsc2VsZWN0ID0gUGxhdGZvcm06R2xvYmFsX1NhbGVzKQpwbGF0Zm9ybXNfMjAxMDwtc3Vic2V0KHBsYXRmb3JtcyxZZWFyPj0yMDEwLHNlbGVjdCA9IFBsYXRmb3JtOkdsb2JhbF9TYWxlcykKCgpzcCA8LSBnZ3Bsb3QocGxhdGZvcm1zXzE5ODAsIGFlcyh4PVllYXIsIHk9R2xvYmFsX1NhbGVzKSkgKwogIGdlb21fcG9pbnQoc2hhcGU9MSkgKwogIGdlb21fbGluZShncm91cCA9IDEpCnNwICsgZmFjZXRfZ3JpZChQbGF0Zm9ybSB+IC4pCgpzcCA8LSBnZ3Bsb3QocGxhdGZvcm1zXzE5OTAsIGFlcyh4PVllYXIsIHk9R2xvYmFsX1NhbGVzKSkgKwogIGdlb21fcG9pbnQoc2hhcGU9MSkgKwogIGdlb21fbGluZShncm91cCA9IDEpCnNwICsgZmFjZXRfd3JhcChQbGF0Zm9ybSB+IC4sIG5jb2w9MykgCgpzcCA8LSBnZ3Bsb3QocGxhdGZvcm1zXzIwMDAsIGFlcyh4PVllYXIsIHk9R2xvYmFsX1NhbGVzKSkgKwogIGdlb21fcG9pbnQoc2hhcGU9MSkgKwogIGdlb21fbGluZShncm91cCA9IDEpCnNwICsgZmFjZXRfd3JhcChQbGF0Zm9ybSB+IC4sIG5jb2w9MykgIAoKc3AgPC0gZ2dwbG90KHBsYXRmb3Jtc18yMDEwLCBhZXMoeD1ZZWFyLCB5PUdsb2JhbF9TYWxlcykpICsKICBnZW9tX3BvaW50KHNoYXBlPTEpICsKICBnZW9tX2xpbmUoZ3JvdXAgPSAxKQpzcCArIGZhY2V0X3dyYXAoUGxhdGZvcm0gfiAuLCBuY29sPTMpICAKCiNQYXJhIGxvcyBncsOhZmljb3MgZGUgbMOtbmVhcywgbG9zIHB1bnRvcyBkZSBkYXRvcyBkZWJlbiBhZ3J1cGFyc2UgcGFyYSBxdWUgc2VwYSBxdcOpIHB1bnRvcyBjb25lY3Rhci4gRW4gZXN0ZSBjYXNvLCBlcyBzaW1wbGU6IHRvZG9zIGxvcyBwdW50b3MgZGViZW4gZXN0YXIgY29uZWN0YWRvcywgcG9yIGxvIHF1ZSBncm91cCA9IDEuIEN1YW5kbyBzZSB1dGlsaXphbiBtw6FzIHZhcmlhYmxlcyB5IHNlIGRpYnVqYW4gdmFyaWFzIGzDrW5lYXMsIGxhIGFncnVwYWNpw7NuIGRlIGzDrW5lYXMgc2UgcmVhbGl6YSBnZW5lcmFsbWVudGUgcG9yIHZhcmlhYmxlLgoKCgoKYGBgCgoKClZlciBxdcOpIGfDqW5lcm9zIHNvbiBtw6FzIHBvcHVsYXJlcyBlbiByZWdpb25lcyB5IGhhbiBjYW1iaWFkbyBhIGxvIGxhcmdvIGRlbCB0aWVtcG8gc2lnbmlmaWNhdGl2YW1lbnRlLgoKVmFtb3MgYSB2ZXIgZWwgVE9QIGRlIGxvcyBnw6luZXJvcyBwb3IgYcOxbwpgYGB7cn0KCiNMYSBmdW5jacOzbiB0b3BfbiB0ZSBwZXJtaXRlIHF1ZWRhcnRlIGNvbiBlbCBwcmltZXIgdmFsb3I6CnRvcF9nZW5yZV95ZWFyIDwtIHZpZGVvX2dhbWVzWyxjKCJHZW5yZSIsIlllYXIiLCJHbG9iYWxfU2FsZXMiKV0KdG9wX2dlbnJlX3llYXIgPC0gdG9wX2dlbnJlX3llYXIgJT4lIGdyb3VwX2J5KFllYXIsR2VucmUpICU+JSBzdW1tYXJpc2UodmVudGFzPXN1bShHbG9iYWxfU2FsZXMpKSAlPiUgdG9wX24oMSkKCnRvcF9nZW5yZV9qYXBhbiA8LSB2aWRlb19nYW1lc1ssYygiR2VucmUiLCJZZWFyIiwiSlBfU2FsZXMiKV0KdG9wX2dlbnJlX2phcGFuIDwtIHRvcF9nZW5yZV9qYXBhbiAlPiUgZ3JvdXBfYnkoWWVhcixHZW5yZSkgJT4lIHN1bW1hcmlzZSh2ZW50YXM9c3VtKEpQX1NhbGVzKSkgJT4lIHRvcF9uKDEpCgpnZ3Bsb3QoZGF0YT10b3BfZ2VucmVfeWVhciwgYWVzKHg9WWVhciwgeT12ZW50YXMsIGZpbGw9R2VucmUpKSArCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsKICAgIGdndGl0bGUoIlRvcCBHZW5lcm8gcG9yIGHDsW8iKSArCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBzaXplID0gMTAsIHZqdXN0ID0gMC40KSxsZWdlbmQucG9zaXRpb24gPSAidG9wIikKCmdncGxvdChkYXRhPXRvcF9nZW5yZV9qYXBhbiwgYWVzKHg9WWVhciwgeT12ZW50YXMsIGZpbGw9R2VucmUpKSArCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsKICAgIGdndGl0bGUoIlRvcCBHZW5lcm8gcG9yIGHDsW8gSmFwb24iKSArCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBzaXplID0gMTAsIHZqdXN0ID0gMC40KSxsZWdlbmQucG9zaXRpb24gPSAidG9wIikKYGBgCk9ic2VydmFtb3MgcXVlIGxhIHByZWZlcmVuY2lhIGVuIGfDqW5lcm8gZGUgdmlkZW9qdWVnbyBlbiBKYXDDs24gZXMgcG9yIGxvcyBqdWVnb3MgZGUgcm9sIG1pZW50cmFzIHF1ZSBnbG9iYWxtZW50ZSBlcyBwb3IgbG9zIGRlIGFjY2nDs24uIEVzdG8gZXMgdW5hIGNhcmFjdGVyw61zdGljYSBjdWFsaXRhdGl2YSBkaWZlcmVuY2lhZG9yYSBkZSBlc3RlIG1lcmNhZG8gcmVzcGVjdG8gYWwgZ2xvYmFsLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tClJlYWxpemFtb3MgdW4gY29udHJhc3RlIENoaSBDdWFkcmFkbyBkZSBib25kYWQgZGUgYWp1c3RlIGRlIGRpbmVybyBlbiB2ZW50YXMgZW4gY2FkYSBnw6luZXJvIGNvbiBsYXMgY29tYmluYWNpb25lczogLSBFVSB2cyBOQSAtIEVVIHZzIEpQIC0gSlAgdnMgTkEKCkFncnVwYW1vcyBkZXNkZSAyMDA4IHF1ZSBlcyBlbCDDumx0aW1vIGNhbWJpbyBkZSBsYSBzZXJpZSB5IGhhY2Vtb3MgY29udHJhc3RlczoKYGBge3J9CkVVX2dlbiA8LSB2aWRlb19nYW1lc1t2aWRlb19nYW1lcyRZZWFyPj0yMDA4LF0gJT4lIGdyb3VwX2J5KEdlbnJlKSAlPiUgCiAgICAgICAgIHN1bW1hcml6ZShSZXZlbnVlID0gc3VtKEVVX1NhbGVzKSkKTkFfZ2VuIDwtIHZpZGVvX2dhbWVzW3ZpZGVvX2dhbWVzJFllYXI+PTIwMDgsXSAlPiUgZ3JvdXBfYnkoR2VucmUpICU+JSAKICAgICAgICAgc3VtbWFyaXplKFJldmVudWUgPSBzdW0oTkFfU2FsZXMpKQpKUF9nZW4gPC0gdmlkZW9fZ2FtZXNbdmlkZW9fZ2FtZXMkWWVhcj49MjAwOCxdICU+JSBncm91cF9ieShHZW5yZSkgJT4lIAogICAgICAgICBzdW1tYXJpemUoUmV2ZW51ZSA9IHN1bShKUF9TYWxlcykpCkdsb2JhbF9nZW4gPC0gdmlkZW9fZ2FtZXNbdmlkZW9fZ2FtZXMkWWVhcj49MjAwOCxdICU+JSBncm91cF9ieShHZW5yZSkgJT4lIAogICAgICAgICBzdW1tYXJpemUoUmV2ZW51ZSA9IHN1bShHbG9iYWxfU2FsZXMpKQpPdGhlcl9nZW4gPC0gdmlkZW9fZ2FtZXNbdmlkZW9fZ2FtZXMkWWVhcj49MjAwOCxdICU+JSBncm91cF9ieShHZW5yZSkgJT4lIAogICAgICAgICBzdW1tYXJpemUoUmV2ZW51ZSA9IHN1bShPdGhlcl9TYWxlcykpCgpOQV9nZW4KYGBgCmBgYHtyfQpnZ3Bsb3QoRVVfZ2VuLGFlcyh4PUdlbnJlLHk9UmV2ZW51ZSkpKwogIGdlb21fYmFyKHN0YXQ9J2lkZW50aXR5JykrIAogIGdndGl0bGUoIkdlbnJlIG9mIEdhbWVzIFB1cmNoYXNlZCBpbiBFVSIpKwogIHlsYWIoIkluIE1pbGxpb25zIikrCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgc2l6ZSA9IDEwLCB2anVzdCA9IDAuNCkpCgoKZ2dwbG90KEpQX2dlbixhZXMoeD1HZW5yZSx5PVJldmVudWUpKSsKICBnZW9tX2JhcihzdGF0PSdpZGVudGl0eScpKyAKICBnZ3RpdGxlKCJHZW5yZSBvZiBHYW1lcyBQdXJjaGFzZWQgaW4gSlAiKSsKICB5bGFiKCJJbiBNaWxsaW9ucyIpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHNpemUgPSAxMCwgdmp1c3QgPSAwLjQpKQoKZ2dwbG90KE5BX2dlbixhZXMoeD1HZW5yZSx5PVJldmVudWUpKSsKICBnZW9tX2JhcihzdGF0PSdpZGVudGl0eScpKyAKICBnZ3RpdGxlKCJHZW5yZSBvZiBHYW1lcyBQdXJjaGFzZWQgaW4gTkEiKSsKICB5bGFiKCJJbiBNaWxsaW9ucyIpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHNpemUgPSAxMCwgdmp1c3QgPSAwLjQpKQoKZ2dwbG90KE5BX2dlbixhZXMoeD1HZW5yZSx5PVJldmVudWUpKSsKICBnZW9tX2JhcihzdGF0PSdpZGVudGl0eScpKyAKICBnZ3RpdGxlKCJHZW5yZSBvZiBHYW1lcyBQdXJjaGFzZWQgaW4gT3RoZXIiKSsKICB5bGFiKCJJbiBNaWxsaW9ucyIpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHNpemUgPSAxMCwgdmp1c3QgPSAwLjQpKQpgYGAKCgoKCgoK